/*
 * Created by SharpDevelop.
 * User: David
 * Date: 2006-12-22
 * Time: 07:20
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */

using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Threading;

using tools;

using Labb4.Main;
using Labb4.Pooman.Players;
using Labb4.Pooman.Cards;
using Labb4.Rules;

namespace Labb4.Pooman.Game
{
	/// <summary>
	/// One stick of the game, continues until one player is declared final player, or winner, of the stick
	/// </summary>
	public class Stick
	{
		#region members
		
		/// <summary>
		/// The rounds of this stick. In the second phase, this will always contain only one round
		/// </summary>
		private List<Round>		m_Rounds;
		/// <summary>
		/// When a winner is found, a reference to that player will be stored here
		/// </summary>
		private Player			m_Winner;
		/// <summary>
		/// This holds a reference to the current player
		/// </summary>
		private Player			m_CurrentPlayer;
		/// <summary>
		/// This will be true if we're supposed to get a new player from the swarm
		/// </summary>
		private bool			m_GetNextPlayer;
		
		/// <summary>
		/// When a stick starts, the number of players in the then untouched swarm is stored here
		/// </summary>
		private int				m_PlayersAtStartOfStick;
		/// <summary>
		/// If the same player picks up cards (phase 2) over and over, the number of times is stored here
		/// </summary>
		private int				m_ConsecutivePickups;
		/// <summary>
		/// Holds a reference to the last player who had to pick up cards, used to determine the number
		/// of consecutive pickups
		/// </summary>
		private Player			m_LastPlayerToPickupCards;
		
		#endregion
		
		#region constructors
		
		/// <summary>
		/// Constructor, initializes members
		/// </summary>
		public Stick()
		{
			Clear();
			
			m_ConsecutivePickups = 0;
			m_LastPlayerToPickupCards = null;
		}
		
		#endregion
		
		#region methods
		
		/// <summary>
		/// Attempts to find a winner of this stick
		/// 
		/// NOTE: only used in phase 1 of the game
		/// </summary>
		/// <param name="swarm">The players competing to become the winner</param>
		/// <returns>True if a winner was found, otherwise false</returns>
		public bool GetWinner(ref PlayerSwarm swarm)
		{
			bool foundWinner = false;
			
			if(m_GetNextPlayer)
			{
				m_CurrentPlayer = swarm.GetNextPlayer();
				m_GetNextPlayer = false;
			}
			
			if(m_CurrentPlayer != null)
			{
				m_CurrentPlayer.Controler.SelectCards();
				
				if(m_CurrentPlayer.Controler.PressedPlay)
				{
					m_GetNextPlayer = true;
					CardPile selectedCards = m_CurrentPlayer.GetSelectedCards();
					
					if(selectedCards.Count > 0)
					{
						m_Rounds[m_Rounds.Count - 1].AddPlay(m_CurrentPlayer, selectedCards);
						Labb4.Rules.PoomanRules.Instance.DealCardsToPlayer(m_CurrentPlayer);
						m_CurrentPlayer.PositionCards();
					}
					else
					{
						MessageBox.Show("Fatal error.. No cards selected..");
					}
				}
			}
			else
			{
				m_GetNextPlayer = true;
			}
			
			if((swarm.Count == 0) && m_GetNextPlayer)
			{
				swarm = m_Rounds[m_Rounds.Count - 1].GetNewSwarm();
				
				if(swarm.CountAtStartOfRound == 1)
				{
					foundWinner = true;
					m_Winner = swarm.GetNextPlayer();
				}
				else
				{
					Round round = new Round();
					round.MoveYposDown(m_Rounds.Count * 120);
					m_Rounds.Add(round);
					
					if(m_Rounds.Count > 2)
					{
						RearrangeCards();
					}
					
					if(swarm.CountAtStartOfRound < 1)
					{
						MessageBox.Show("New swarm concists of 0 players.. Why?", "Major problem in Stick.GetWinner");
					}
				}
			}
			
			return foundWinner;
		}
		
		/// <summary>
		/// Attempts to determine the last player of the stick
		/// 
		/// NOTE: only used in phase 2 of the gamme
		/// </summary>
		/// <param name="swarm">The players competing to become the last player</param>
		/// <returns>True if a last player was found, otherwise false</returns>
		public bool GetLastPlayer(ref PlayerSwarm swarm)
		{
			bool foundWinner = false;
			
			if(m_PlayersAtStartOfStick == 0)
			{
				m_PlayersAtStartOfStick = swarm.Count;
			}
			
			if(m_GetNextPlayer)
			{
				m_CurrentPlayer = swarm.GetNextPlayer();
				swarm.AddPlayer(m_CurrentPlayer);
				m_GetNextPlayer = false;
			}
			
			if(m_CurrentPlayer != null)
			{
				m_CurrentPlayer.Controler.SelectCards();
				
				if(m_CurrentPlayer.Controler.PressedPlay)
				{
					m_GetNextPlayer = true;
					CardPile selectedCards = m_CurrentPlayer.GetSelectedCards();
					
					if(selectedCards.Count > 0)
					{
						m_Rounds[m_Rounds.Count - 1].AddPlay(m_CurrentPlayer, selectedCards);
						m_CurrentPlayer.PositionCards();
					}
					else
					{
						//player couldn't top the cards, so he has to pick up the bottom cards..
						Table.Instance.GetCards(m_CurrentPlayer);
						//a player can only pick up cards 3 times in a row (if there's only 2 players left in the game
						if(swarm.Count == 2)
						{
							if(m_CurrentPlayer == m_LastPlayerToPickupCards)
							{
								m_ConsecutivePickups++;
								
								if(m_ConsecutivePickups == 3)
								{
									m_ConsecutivePickups = 0;
									m_LastPlayerToPickupCards = null;
									swarm.Clear();
									PlayerManager.Instance.GetNextSwarm(m_CurrentPlayer, swarm);
								}
							}
							else
							{
								m_LastPlayerToPickupCards = m_CurrentPlayer;
								m_ConsecutivePickups = 1;
							}
						}
						
						//if player 2 plays its final cards, and player 3 has to pick up cards,
						//then the number of plays needed to turn the cards should be changed.
						m_PlayersAtStartOfStick = swarm.Count;
					}
				}
			}
			else
			{
				m_GetNextPlayer = true;
			}
			
			if((swarm.Count == 0) && m_GetNextPlayer)
			{
				//this has never happened
				MessageBox.Show("Fatal error in phase 2 stick. No players in the swarm, when there should be..");
			}
			
			//if there are as many plays in the round as there were players in the swarm from the start
			//of the stick, then we're about to turn the cards..
			//and the last player should start the next stick
			if(m_Rounds[0].Plays == m_PlayersAtStartOfStick)
			{
				foundWinner = true;
				m_Winner = m_CurrentPlayer;
			}
			
			//if the current player has no cards on hand, this player has to be removed from the swarm.
			if(m_CurrentPlayer.CurrentHand.Cards.Count == 0)
			{
				swarm.RemovePlayer(m_CurrentPlayer);
			}
			
			return foundWinner;
		}
		
		/// <summary>
		/// Clears the stick, initializing it to take the first play
		/// </summary>
		public void Clear()
		{
			if(m_Rounds == null)
			{
				m_Rounds = new List<Round>();
			}
			else
			{
				m_Rounds.Clear();
			}
			
			m_Winner = null;
			m_CurrentPlayer = null;
			m_GetNextPlayer = true;
			
			m_Rounds.Add(new Round());
			m_PlayersAtStartOfStick = 0;
		}
		
		/// <summary>
		/// Gets all the cards in all the rounds of the stick
		/// </summary>
		/// <returns>A collection of cards containing all the cards played in this stick</returns>
		public CardPile GetAllCards()
		{
			CardPile allCards = new CardPile();
			
			foreach(Round it in m_Rounds)
			{
				allCards.Add(it.GetAndRemoveAllCards());
			}
			
			m_Rounds.Clear();
			
			return allCards;
		}
		
		/// <summary>
		/// Saves the stick to a List of string
		/// </summary>
		/// <param name="fileContent">The List of string to save the stick to</param>
		public void Save(List<string> fileContent)
		{
			string winner = "null";
			string currentPlayer = "null";
			string getNextPlayer = m_GetNextPlayer.ToString().ToLower();
			string playersAtStartOfStick = m_PlayersAtStartOfStick.ToString();
			string consecutivePickups = m_ConsecutivePickups.ToString();
			string lastPlayerToPickupCards = "null";
			
			if(m_Winner != null)
			{
				winner = PlayerManager.Instance[m_Winner].ToString();
			}
			
			if(m_CurrentPlayer != null)
			{
				currentPlayer = PlayerManager.Instance[m_CurrentPlayer].ToString();
			}
			
			if(m_LastPlayerToPickupCards != null)
			{
				lastPlayerToPickupCards = PlayerManager.Instance[m_LastPlayerToPickupCards].ToString();
			}
			
			fileContent.Add("stick_winner " + winner);
			fileContent.Add("stick_current_player " + currentPlayer);
			fileContent.Add("get_next_player " + getNextPlayer);
			fileContent.Add("players_at_start_of_stick " + playersAtStartOfStick);
			fileContent.Add("consecutive_pickups " + consecutivePickups);
			fileContent.Add("last_player_to_pick_up_cards " + lastPlayerToPickupCards);
			fileContent.Add("rounds " + m_Rounds.Count.ToString());
			int round = 0;
			
			foreach(Round it in m_Rounds)
			{
				it.Save(fileContent, round);
				round++;
			}
		}
		
		/// <summary>
		/// Loads a stick from a file
		/// </summary>
		/// <param name="config">The file to load from</param>
		public void Load(Config config)
		{
			m_Winner = null;
			m_CurrentPlayer = null;
			m_LastPlayerToPickupCards = null;
			m_Rounds.Clear();
			
			string winner = "";
			string currentPlayer = "";
			string lastPlayerToPickupCards = "";
			int rounds = 0;
			
			if(MainForm.ErrorCheck(config.GetString("stick_winner", ref winner)) &&
			   MainForm.ErrorCheck(config.GetString("stick_current_player", ref currentPlayer)) &&
			   MainForm.ErrorCheck(config.GetBool("get_next_player", ref m_GetNextPlayer)) &&
			   MainForm.ErrorCheck(config.GetInt("players_at_start_of_stick", ref m_PlayersAtStartOfStick)) &&
			   MainForm.ErrorCheck(config.GetInt("consecutive_pickups", ref m_ConsecutivePickups)) &&
			   MainForm.ErrorCheck(config.GetString("last_player_to_pick_up_cards", ref lastPlayerToPickupCards)) &&
			   MainForm.ErrorCheck(config.GetInt("rounds", ref rounds)))
			{
				
				if(!winner.Equals("null"))
				{
					m_Winner = PlayerManager.Instance[int.Parse(winner)];
				}
				
				if(!currentPlayer.Equals("null"))
				{
					m_CurrentPlayer = PlayerManager.Instance[int.Parse(currentPlayer)];
				}
				
				if(!lastPlayerToPickupCards.Equals("null"))
				{
					m_LastPlayerToPickupCards = PlayerManager.Instance[int.Parse(lastPlayerToPickupCards)];
				}
				
				for(int i = 0; i < rounds; i++)
				{
					Round round = new Round();
					round.Load(config, i);
					m_Rounds.Add(round);
				}
			}
		}
		
		#endregion
		
		#region properties
		
		/// <summary>
		/// The winner of this stick (get)
		/// </summary>
		public Player Winner
		{
			get
			{
				return m_Winner;
			}
		}
		
		#endregion
		
		#region private methods
		
		/// <summary>
		/// Rearranges the played cards over the screen
		/// </summary>
		private void RearrangeCards()
		{
			int y = 50;
			int yInc = (280 / m_Rounds.Count);
			
			foreach(Round it in m_Rounds)
			{
				it.RearrangeCards(y);
				y += yInc;
			}
		}
		
		#endregion
	}
}
